﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.ComponentModel;

using Resxus.Model;

namespace Resxus.DataAccess
{
    public class ResourceTable : ICollection<ResourceRecord>
    {
        public event Action<object, DataChangedEventArgs<ResourceRecord>> DataChanged;
        public event Action<ResourceRecord> AddRecord;
        public event Action ClearRecords;
        public event Action<ResourceRecord> RemoveRecord;


    #region Private Helpers 

        private void RaiseEvent(Action action)
        {
            if (action != null)
            {
                action();
            }
        }

        private void RaiseEvent(Action<ResourceRecord> action, ResourceRecord item)
        {
            if (action != null)
            {
                action(item);
            }
        }
        
        private void RaiseEvent(DataChangedEventArgs<ResourceRecord> args)            
        {
            if (this.DataChanged != null)
            {
                this.DataChanged(this, args);
            }            
        }

    #endregion

        /// <summary>
        /// 레코드 객체
        /// </summary>
        private Dictionary<string, ResourceRecord> _Records = new Dictionary<string, ResourceRecord>();

        /// <summary>
        /// 레코드 인터페이스 접근
        /// </summary>
        public ICollection<ResourceRecord> Items
        {
            get
            {
                return this;
            }
        }

        /// <summary>
        /// 연관된 리소스 파일
        /// </summary>
        public ResourceFile File
        {
            get;
            private set;
        }

        /// <summary>
        /// 생성자
        /// </summary>
        /// <param name="file">연관된 리소스 파일</param>
        public ResourceTable(ResourceFile file)
        {
            this.File = file;            
        }

        /// <summary>
        /// 저장소의 레코드 내용에 변경이 일어날때 아래 이벤트 발생함 (이 부분에서 Model과 
        /// </summary>        
        void Record_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {  
            if (e.PropertyName.Equals("ID") == true)
            {
                PropertyNotificationEventArgs args = e as PropertyNotificationEventArgs;
                if (this.Contains(args.NewValue as string) == true)
                {
                    ResourceRecord record = null;
                    if (this._Records.TryGetValue(args.NewValue as string, out record) == true)
                    {
                        record.ID = args.
                    }
                    
                }
                 
            }         

            if (e.PropertyName.Equals("IsMatch") == false)
            {
                this.RaiseEvent(new DataChangedEventArgs<ResourceRecord>(sender as ResourceRecord, 
                                                                         DataChangedEventArgs<ResourceRecord>.ChangeAction.Update, 
                                                                         e as PropertyNotificationEventArgs));
            }            
        }

        #region ICollection<ResourceRecord> 멤버

        /// <summary>
        /// 저장소에 새 레코드 추가
        /// </summary>
        /// <param name="item">레코드</param>
        void ICollection<ResourceRecord>.Add(ResourceRecord item)
        {            
            this._Records.Add(item.ID, item);
            item.PropertyChanged += new PropertyChangedEventHandler(Record_PropertyChanged);
                        
            this.RaiseEvent(this.AddRecord, item);
            this.RaiseEvent(new DataChangedEventArgs<ResourceRecord>(item, DataChangedEventArgs<ResourceRecord>.ChangeAction.Add));
        }

        /// <summary>
        /// 전체 레코드 삭제
        /// </summary>
        void ICollection<ResourceRecord>.Clear()
        {
            this._Records.Clear();

            this.RaiseEvent(this.ClearRecords);            
            this.RaiseEvent(new DataChangedEventArgs<ResourceRecord>(DataChangedEventArgs<ResourceRecord>.ChangeAction.Clear));
        }

        /// <summary>
        /// ID 존재여부 검사
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns>존재여부</returns>
        public bool Contains(string id)
        {
            return this._Records.ContainsKey(id);
        }

        /// <summary>
        /// 레코드 존재여부 검사
        /// </summary>
        /// <param name="item">레코드</param>
        /// <returns>존재여부</returns>
        bool ICollection<ResourceRecord>.Contains(ResourceRecord item)
        {
            ResourceRecord result = null;
            bool found = this._Records.TryGetValue(item.ID, out result);
            if (found == true)
            {
                return result.Equals(item);
            }

            return false;
        }

        /// <summary>
        /// 레코드 복사
        /// </summary>
        /// <param name="array"></param>
        /// <param name="arrayIndex"></param>
        void ICollection<ResourceRecord>.CopyTo(ResourceRecord[] array, int arrayIndex)
        {
            this._Records.Values.CopyTo(array, arrayIndex);
        }

        /// <summary>
        /// 레코드 수
        /// </summary>
        int ICollection<ResourceRecord>.Count
        {
            get { return this._Records.Count; }
        }

        /// <summary>
        /// 읽기전용 여부
        /// </summary>
        bool ICollection<ResourceRecord>.IsReadOnly
        {
            get { return false; }
        }
        
        /// <summary>
        /// 레코드 삭제
        /// </summary>
        /// <param name="item">삭제할 레코드</param>
        /// <returns>삭제여부</returns>
        bool ICollection<ResourceRecord>.Remove(ResourceRecord item)
        {
            item.PropertyChanged -= new PropertyChangedEventHandler(Record_PropertyChanged);
            bool result = this.Items.Remove(item);

            this.RaiseEvent(this.RemoveRecord, item);
            this.RaiseEvent(new DataChangedEventArgs<ResourceRecord>(DataChangedEventArgs<ResourceRecord>.ChangeAction.Remove));

            return result;             
        }

        #endregion

        #region IEnumerable<ResourceRecord> 멤버

        IEnumerator<ResourceRecord> IEnumerable<ResourceRecord>.GetEnumerator()
        {
            return this._Records.Values.GetEnumerator();
        }

        #endregion

        #region IEnumerable 멤버

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return this._Records.GetEnumerator();
        }

        #endregion
    }
}
